package com.chongba.schedule;

import java.util.Calendar;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author: admin
 * @time: 2022/12/1 15:16
 */
public class DelayedTask implements Delayed {

    private int executeTime;

    public DelayedTask(int delay) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, delay);
        this.executeTime = (int) (calendar.getTimeInMillis() / 1000);
    }
    /*DelayQueue 是一个支持延时获取元素的阻塞队列， 内部采用优先队列 PriorityQueue 存储元素，同时元素
    必须实现 Delayed 接口；在创建元素时可以指定多久才可以从队列中获取当前元素，只有在延迟期满时才能从队
    列中提取元素。*/

    /*DelayQueue属于排序队列，它的特殊之处在于队列的元素必须实现Delayed接口，该接口需要实现
            compareTo和getDelay方法 */
    /* getDelay方法：获取元素在队列中的剩余时间，只有当剩余时间为0时元素才可以出队列。 */
    @Override
    public long getDelay(TimeUnit unit) {
        return executeTime - (int) (System.currentTimeMillis() / 1000);
    }

    /* compareTo方法：用于排序，确定元素出队列的顺序。*/
    @Override
    public int compareTo(Delayed o) {
        long l = this.getDelay(TimeUnit.SECONDS) - o.getDelay(TimeUnit.SECONDS);
        return l == 0 ? 0 : (l < 0 ? -1 : 1);
    }

   /* 使用线程池或者原生DelayQueue程序挂掉之后，任务都是放在内存，需要考虑未处理消息的丢失带来的影响，如何保
    证数据不丢失，需要持久化（磁盘）*/
    public static void main(String[] args) {
        DelayQueue<DelayedTask> delayedTasks = new DelayQueue<>();
        delayedTasks.add(new DelayedTask(5));
        delayedTasks.add(new DelayedTask(10));
        delayedTasks.add(new DelayedTask(15));

        System.out.println(System.currentTimeMillis()/1000+"开始消费");
        while (delayedTasks.size() !=0){
            DelayedTask poll = delayedTasks.poll();
            if (poll != null){
                System.out.println(System.currentTimeMillis()/1000+"消费任务");
            }
        }
    }
}
